package com.xy.tool.data.redis.core;

import com.xy.lang.exception.BaseSysException;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.function.Function;

public final class Id<T> extends Namespace {

    private T value;

    public Id(String name, String domain) {
        super(name, domain);
    }

    public Id(String name, String domain, T value) {
        super(name, domain);
        Objects.requireNonNull(value, "The value of id is required.");
        of(value);
    }

    public Id(Namespace namespace, T value) {
        super(namespace.getName(), namespace.getDomain());
        Objects.requireNonNull(value, "The value of id is required.");
        of(value);
    }

    public final Id of(T value) {
        Class<?> clazz = value.getClass();
        if(String.class != clazz
            && int.class != clazz
            && Integer.class != clazz
            && long.class != clazz
            && Long.class != clazz) {
            throw new BaseSysException();
        }
        this.value = value;
        return this;
    }

    public final String toKey() {
        return toString();
    }

    @Override
    public final String toString() {
        return concat(getSeparator(), name, domain, String.valueOf(value));
    }

    public final T getValue() {
        return value;
    }

    public static Id<String> parse(String value, char separator) {
        return parse(value, separator, e -> e);
    }

    public static Id<Integer> parseInt(String value, char separator) {
        return parse(value, separator, e -> StringUtils.hasText(e) ? Integer.parseInt(e) : null);
    }

    public static Id<Long> parseLong(String value, char separator) {
        return parse(value, separator, e -> StringUtils.hasText(e) ? Long.parseLong(e) : null);
    }

    public static <TT> Id<TT> parse(String value, char separator, Function<String, TT> converter) {
        if(separator < 0) {
            throw new IllegalArgumentException("invalid separator");
        }
        if(null == converter) {
            Objects.requireNonNull(converter, "The converter is required.");
        }
        if(value == null || value.length() == 0) {
            return null;
        }
        int firstIndex = value.indexOf(separator);
        if(firstIndex < 0) {
            return null;
        }
        String namespace = value.substring(0, firstIndex);
        int secondIndex = value.indexOf(separator, firstIndex + 1);
        if(secondIndex < 0 || secondIndex > value.length()) {
            return null;
        }
        return new Id(namespace,
                value.substring(firstIndex + 1, secondIndex),
                converter.apply(value.substring(secondIndex + 1)));
    }


    /// tests

    public static void main(String[] args) {
        char separator = DEFAULT_SEPARATOR;
        System.out.println(parse(null, separator));
        System.out.println(parse("", separator));
        System.out.println(parse("a", separator));
        System.out.println(parse("a" + separator, separator));
        System.out.println(parse("a" + separator + null, separator));
        System.out.println(parse("a" + separator + "", separator));
        System.out.println(parse("a" + separator + "b", separator));
        System.out.println(parse("a" + separator + "b" + separator, separator));
        System.out.println(parse("a" + separator + "b" + separator + null, separator));
        System.out.println(parse("a" + separator + "b" + separator + "", separator));
        System.out.println(parse("a" + separator + "b" + separator + "c", separator));
        System.out.println(parse("a" + separator + "b" + separator + "c" + separator, separator));
        System.out.println(parse("a" + separator + "b" + separator + "c" + separator + null, separator));
        System.out.println(parse("a" + separator + "b" + separator + "c" + separator + "", separator));
        System.out.println(parse("a" + separator + "b" + separator + "c" + separator + "d", separator));
    }

}
